package com.xuexi.mashibing;

import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.NoArgsConstructor;

/**
 * 哲学家吃饭问题，5个哲学家围着桌子要吃饭，5为哲学家每人中间放一根筷子，只有拿到左右两根筷子才能吃饭
 */
public class PhilosopherEatFoodQuestion {

    public static void main(String[] args) {
        //Chopsticks 编号
        Chopsticks c1 = new Chopsticks();
        Chopsticks c2 = new Chopsticks();
        Chopsticks c3 = new Chopsticks();
        Chopsticks c4 = new Chopsticks();
        Chopsticks c5 = new Chopsticks();

        Philosopher ph1 = new Philosopher("张三", 1, c1, c2);
        Philosopher ph2 = new Philosopher("李四", 2, c2, c3);
        Philosopher ph3 = new Philosopher("王五", 3, c3, c4);
        Philosopher ph4 = new Philosopher("小六", 4, c4, c5);
        Philosopher ph5 = new Philosopher("老七", 5, c5, c1);

        ph1.start();
        ph2.start();
        ph3.start();
        ph4.start();
        ph5.start();
    }

    /**
     * 哲学家：线程
     */
    @EqualsAndHashCode(callSuper = true)
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public static class Philosopher extends Thread {
        private String userName;

        private Integer index;

        private Chopsticks left, right;


        /*
        * 一个典型的死锁问题出现了
        *
        */
        public void run() {
            synchronized (left) {
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    throw new RuntimeException(e);
                }
                synchronized (right) {
                    try {
                        System.out.println("第" + index + "号哲学家：" + userName + "拿到了筷子开始吃饭。。。。。");
                        Thread.sleep(1000);
                        System.out.println("第" + index + "号哲学家：" + userName + "吃饭结束");
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }


        /*
        * 方式一：尝试让一个人先拿左边的筷子，其他人先拿右边的筷子
        * 方式二：隔一个人
        * */
        /*@Override
        public void run() {
            if (index == 3) {
                synchronized (left) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    synchronized (right) {
                        try {
                            System.out.println("第" + index + "号哲学家：" + userName + "拿到了筷子开始吃饭。。。。。");
                            Thread.sleep(1000);
                            System.out.println("第" + index + "号哲学家：" + userName + "吃饭结束");
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            } else {
                synchronized (right) {
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                    synchronized (left) {
                        try {
                            System.out.println("第" + index + "号哲学家：" + userName + "拿到了筷子开始吃饭。。。。。");
                            Thread.sleep(1000);
                            System.out.println("第" + index + "号哲学家：" + userName + "吃饭结束");
                        } catch (InterruptedException e) {
                            throw new RuntimeException(e);
                        }
                    }
                }
            }
        }*/
    }

    /**
     * 筷子：资源
     */
    public static class Chopsticks {

    }

}
